package com.crawler.system.service.impl;

import com.crawler.system.dto.DynamicPageParamsDTO;
import com.crawler.system.dto.ElementWaitDTO;
import com.crawler.system.dto.PageInteractionDTO;
import com.crawler.system.entity.CrawlerResult;
import com.crawler.system.entity.CrawlerRule;
import com.crawler.system.repository.CrawlerRuleRepository;
import com.crawler.system.repository.CrawlerResultRepository;
import com.crawler.system.repository.CrawlerTaskRepository;
import com.crawler.system.service.AbstractCrawlerEngine;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 动态页面爬虫引擎
 * 使用Selenium WebDriver实现动态JavaScript渲染页面的爬取
 */
@Slf4j
@Service
public class DynamicCrawlerEngine extends AbstractCrawlerEngine {

    private WebDriver driver;
    private List<CrawlerRule> rules;
    private DynamicPageParamsDTO dynamicParams;
    
    /**
     * 运行状态标志
     */
    private final AtomicBoolean running = new AtomicBoolean(false);
    
    /**
     * 暂停状态标志
     */
    private final AtomicBoolean paused = new AtomicBoolean(false);

    @Value("${crawler.config.webdriver.chrome:}")
    private String chromeDriverPath;

    private CrawlerRuleRepository ruleRepository;

    private ObjectMapper objectMapper;

    /**
     * 默认构造函数
     */
    public DynamicCrawlerEngine() {
        super();
    }
    
    /**
     * 构造函数
     * 
     * @param taskRepository 爬虫任务仓库
     * @param resultRepository 爬虫结果仓库
     * @param ruleRepository 爬虫规则仓库
     * @param objectMapper JSON对象映射器
     */
    public DynamicCrawlerEngine(
        CrawlerTaskRepository taskRepository, 
        CrawlerResultRepository resultRepository,
        CrawlerRuleRepository ruleRepository,
        ObjectMapper objectMapper
    ) {
        super(taskRepository, resultRepository);
        this.ruleRepository = ruleRepository;
        this.objectMapper = objectMapper;
    }
    
    /**
     * 设置爬虫规则仓库
     * 
     * @param ruleRepository 爬虫规则仓库
     */
    public void setRuleRepository(CrawlerRuleRepository ruleRepository) {
        this.ruleRepository = ruleRepository;
    }
    
    /**
     * 设置JSON对象映射器
     * 
     * @param objectMapper JSON对象映射器
     */
    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
    
    /**
     * 设置Chrome驱动路径
     * 
     * @param chromeDriverPath Chrome驱动路径
     */
    public void setChromeDriverPath(String chromeDriverPath) {
        this.chromeDriverPath = chromeDriverPath;
    }

    @Override
    public List<Long> start() {
        if (task == null) {
            setErrorMessage("爬虫任务未初始化");
            return Collections.emptyList();
        }

        // 加载爬虫规则
        loadRules();

        // 加载动态页面参数
        loadDynamicParams();

        List<Long> resultIds = new ArrayList<>();
        running.set(true);
        paused.set(false);
        progress.set(0);

        try {
            // 更新任务状态
            updateTaskStatus("RUNNING");

            // 初始化WebDriver
            initWebDriver();

            // 访问目标URL
            log.info("访问目标URL: {}", task.getTargetUrl());
            driver.get(task.getTargetUrl());
            progress.set(10);

            // 等待页面加载
            int waitTime = dynamicParams != null && dynamicParams.getWaitTime() != null ? 
                    dynamicParams.getWaitTime() : 3000;
            Thread.sleep(waitTime);
            progress.set(20);

            // 等待页面元素
            if (dynamicParams != null && dynamicParams.getElementWaits() != null && !dynamicParams.getElementWaits().isEmpty()) {
                waitForElements();
            }
            progress.set(30);

            // 执行页面交互操作
            if (dynamicParams != null && dynamicParams.getInteractions() != null && !dynamicParams.getInteractions().isEmpty()) {
                performInteractions();
            }
            progress.set(50);

            // 执行自定义脚本
            if (dynamicParams != null && dynamicParams.getCustomScript() != null && !dynamicParams.getCustomScript().isEmpty()) {
                executeCustomScript(dynamicParams.getCustomScript());
            }
            progress.set(60);

            // 截取页面截图
            String screenshotPath = null;
            if (dynamicParams != null && dynamicParams.getTakeScreenshot() != null && dynamicParams.getTakeScreenshot()) {
                screenshotPath = takeScreenshot();
            }
            progress.set(70);

            // 获取页面内容
            String pageSource = driver.getPageSource();
            String pageTitle = driver.getTitle();
            String currentUrl = driver.getCurrentUrl();
            progress.set(80);

            // 提取页面数据
            Map<String, Object> extractedData = extractContent();
            progress.set(90);

            // 保存结果
            CrawlerResult result = new CrawlerResult();
            result.setTaskId(task.getId());
            result.setSourceUrl(currentUrl);
            result.setTitle(pageTitle);
            result.setHtmlContent(pageSource);
            result.setContentSize((long) pageSource.length());
            result.setStatusCode(200); // 假设成功
            result.setContentType("text/html");
            result.setDepth(1);
            result.setFetchTime(LocalDateTime.now());
            result.setProcessStatus("PROCESSED");
            result.setCreateTime(LocalDateTime.now());
            result.setExtractedData(extractedData);
            result.setCategories(screenshotPath != null ? "screenshot" : null);

            Long resultId = saveResult(result);
            resultIds.add(resultId);

            // 更新任务状态
            progress.set(100);
            updateTaskStatus("COMPLETED");

            // 更新统计信息
            statistics.put("successUrls", 1);
            statistics.put("totalUrls", 1);
            statistics.put("totalSize", pageSource.length());

        } catch (Exception e) {
            setErrorMessage("动态爬取任务执行异常: " + e.getMessage());
            log.error("动态爬取任务执行异常", e);
            updateTaskStatus("FAILED");
        } finally {
            running.set(false);
            if (driver != null) {
                try {
                    driver.quit();
                } catch (Exception e) {
                    log.error("关闭WebDriver失败", e);
                }
                driver = null;
            }
        }

        return resultIds;
    }

    /**
     * 初始化WebDriver
     */
    private void initWebDriver() {
        // 使用最新的Selenium 4.x配置方式
        System.setProperty("webdriver.chrome.driver", chromeDriverPath);
        
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless"); // 无头模式
        options.addArguments("--disable-gpu");
        options.addArguments("--no-sandbox");
        options.addArguments("--disable-dev-shm-usage");

        // 设置窗口大小
        if (dynamicParams != null) {
            if (dynamicParams.getWindowWidth() != null && dynamicParams.getWindowHeight() != null) {
                options.addArguments("--window-size=" + dynamicParams.getWindowWidth() + "," + dynamicParams.getWindowHeight());
            }
            
            // 设置用户代理
            if (dynamicParams.getUserAgent() != null) {
                options.addArguments("--user-agent=" + dynamicParams.getUserAgent());
            } else if (userAgent != null) {
                options.addArguments("--user-agent=" + userAgent);
            }
            
            // 禁用图片加载
            if (dynamicParams.getImagesEnabled() != null && !dynamicParams.getImagesEnabled()) {
                Map<String, Object> prefs = new HashMap<>();
                prefs.put("profile.default_content_setting_values.images", 2);
                options.setExperimentalOption("prefs", prefs);
            }
            
            // 禁用JavaScript
            if (dynamicParams.getJavascriptEnabled() != null && !dynamicParams.getJavascriptEnabled()) {
                options.addArguments("--disable-javascript");
            }
        }

        driver = new ChromeDriver(options);
        
        // 设置页面加载超时
        driver.manage().timeouts().pageLoadTimeout(Duration.ofMillis(timeout));
        
        // 设置Cookie
        if (dynamicParams != null && dynamicParams.getCookies() != null) {
            driver.get("about:blank");
            for (Map.Entry<String, String> entry : dynamicParams.getCookies().entrySet()) {
                Cookie cookie = new Cookie(entry.getKey(), entry.getValue());
                driver.manage().addCookie(cookie);
            }
        }
    }

    /**
     * 等待页面元素
     */
    private void waitForElements() {
        if (dynamicParams.getElementWaits() == null || dynamicParams.getElementWaits().isEmpty()) {
            return;
        }
        
        for (ElementWaitDTO waitConfig : dynamicParams.getElementWaits()) {
            try {
                int timeout = waitConfig.getTimeout() != null ? waitConfig.getTimeout() : 10000;
                WebDriverWait wait = new WebDriverWait(driver, Duration.ofMillis(timeout));
                
                By selector = "CSS".equals(waitConfig.getSelectorType()) ?
                        By.cssSelector(waitConfig.getSelector()) :
                        By.xpath(waitConfig.getSelector());
                
                switch (waitConfig.getWaitType()) {
                    case "PRESENCE":
                        wait.until(ExpectedConditions.presenceOfElementLocated(selector));
                        break;
                    case "VISIBILITY":
                        wait.until(ExpectedConditions.visibilityOfElementLocated(selector));
                        break;
                    case "CLICKABLE":
                        wait.until(ExpectedConditions.elementToBeClickable(selector));
                        break;
                    default:
                        wait.until(ExpectedConditions.presenceOfElementLocated(selector));
                }
                log.info("等待元素成功: {}", waitConfig.getSelector());
            } catch (Exception e) {
                log.error("等待元素失败: " + waitConfig.getSelector(), e);
                if (waitConfig.getIgnoreTimeout() == null || !waitConfig.getIgnoreTimeout()) {
                    throw e;
                }
            }
        }
    }

    /**
     * 执行页面交互操作
     */
    private void performInteractions() {
        if (dynamicParams.getInteractions() == null || dynamicParams.getInteractions().isEmpty()) {
            return;
        }
        
        // 对交互操作按顺序排序
        List<PageInteractionDTO> interactions = new ArrayList<>(dynamicParams.getInteractions());
        interactions.sort(Comparator.comparing(PageInteractionDTO::getOrder, Comparator.nullsFirst(Integer::compareTo)));
        
        for (PageInteractionDTO interaction : interactions) {
            try {
                switch (interaction.getType()) {
                    case "CLICK":
                        performClick(interaction);
                        break;
                    case "SCROLL":
                        performScroll(interaction);
                        break;
                    case "INPUT":
                        performInput(interaction);
                        break;
                    case "HOVER":
                        performHover(interaction);
                        break;
                    case "WAIT":
                        performWait(interaction);
                        break;
                    case "SCRIPT":
                        executeCustomScript(interaction.getScript());
                        break;
                    default:
                        log.warn("不支持的交互类型: {}", interaction.getType());
                }
                log.info("执行交互操作成功: {}", interaction.getType());
            } catch (Exception e) {
                log.error("执行交互操作失败: " + interaction.getType(), e);
            }
        }
    }

    /**
     * 执行点击操作
     */
    private void performClick(PageInteractionDTO interaction) {
        WebElement element = findElement(interaction.getSelector(), interaction.getSelectorType());
        if (element != null) {
            element.click();
        }
    }

    /**
     * 执行滚动操作
     */
    private void performScroll(PageInteractionDTO interaction) {
        if (interaction.getScrollX() != null && interaction.getScrollY() != null) {
            String script = "window.scrollBy(" + interaction.getScrollX() + "," + interaction.getScrollY() + ");";
            executeCustomScript(script);
        } else if (interaction.getSelector() != null) {
            WebElement element = findElement(interaction.getSelector(), interaction.getSelectorType());
            if (element != null) {
                String script = "arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});";
                executeCustomScript(script, element);
            }
        }
    }

    /**
     * 执行输入操作
     */
    private void performInput(PageInteractionDTO interaction) {
        WebElement element = findElement(interaction.getSelector(), interaction.getSelectorType());
        if (element != null && interaction.getValue() != null) {
            element.clear();
            element.sendKeys(interaction.getValue());
        }
    }

    /**
     * 执行悬停操作
     */
    private void performHover(PageInteractionDTO interaction) {
        WebElement element = findElement(interaction.getSelector(), interaction.getSelectorType());
        if (element != null) {
            String script = "var event = new MouseEvent('mouseover', {'bubbles': true, 'cancelable': true}); arguments[0].dispatchEvent(event);";
            executeCustomScript(script, element);
        }
    }

    /**
     * 执行等待操作
     */
    private void performWait(PageInteractionDTO interaction) throws InterruptedException {
        int waitTime = interaction.getWaitTime() != null ? interaction.getWaitTime() : 1000;
        Thread.sleep(waitTime);
    }

    /**
     * 查找元素
     */
    private WebElement findElement(String selector, String selectorType) {
        try {
            By by = "CSS".equals(selectorType) ?
                    By.cssSelector(selector) :
                    By.xpath(selector);
            return driver.findElement(by);
        } catch (Exception e) {
            log.error("查找元素失败: " + selector, e);
            return null;
        }
    }

    /**
     * 执行自定义JavaScript脚本
     */
    private Object executeCustomScript(String script, Object... args) {
        if (script == null || script.isEmpty()) {
            return null;
        }
        try {
            JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
            return jsExecutor.executeScript(script, args);
        } catch (Exception e) {
            log.error("执行JavaScript脚本失败", e);
            return null;
        }
    }

    /**
     * 截取页面截图
     */
    private String takeScreenshot() {
        try {
            File screenshotFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
            String fileName = "screenshot_" + task.getId() + "_" + System.currentTimeMillis() + ".png";
            String outputPath = "screenshots/" + fileName;
            
            // 确保目录存在
            File outputDir = new File("screenshots");
            if (!outputDir.exists()) {
                outputDir.mkdirs();
            }
            
            // 移动文件
            boolean moved = screenshotFile.renameTo(new File(outputPath));
            if (moved) {
                log.info("截图保存成功: {}", outputPath);
                return outputPath;
            } else {
                log.error("截图保存失败");
                return null;
            }
        } catch (Exception e) {
            log.error("截取截图失败", e);
            return null;
        }
    }

    /**
     * 提取页面数据
     */
    private Map<String, Object> extractContent() {
        Map<String, Object> content = new HashMap<>();
        
        try {
            // 如果没有规则，则返回空内容
            if (rules == null || rules.isEmpty()) {
                return content;
            }
            
            // 遍历所有规则
            for (CrawlerRule rule : rules) {
                try {
                    // 判断URL是否匹配规则
                    String currentUrl = driver.getCurrentUrl();
                    if (!isUrlMatchRule(currentUrl, rule.getUrlPattern())) {
                        continue;
                    }
                    
                    // 根据选择器类型提取内容
                    String selectorType = rule.getSelectorType();
                    String selector = rule.getSelector();
                    String extractType = rule.getExtractType();
                    
                    if (selector == null || selector.isEmpty()) {
                        continue;
                    }
                    
                    Object extractedValue = null;
                    
                    if ("CSS".equals(selectorType)) {
                        // CSS选择器
                        if ("TEXT".equals(extractType)) {
                            extractedValue = extractTextByCSS(selector);
                        } else if ("ATTRIBUTE".equals(extractType)) {
                            extractedValue = extractAttributeByCSS(selector, rule.getAttributeName());
                        } else if ("HTML".equals(extractType)) {
                            extractedValue = extractHtmlByCSS(selector);
                        } else if ("LIST".equals(extractType)) {
                            extractedValue = extractListByCSS(selector);
                        }
                    } else if ("XPATH".equals(selectorType)) {
                        // XPath选择器
                        if ("TEXT".equals(extractType)) {
                            extractedValue = extractTextByXPath(selector);
                        } else if ("ATTRIBUTE".equals(extractType)) {
                            extractedValue = extractAttributeByXPath(selector, rule.getAttributeName());
                        } else if ("HTML".equals(extractType)) {
                            extractedValue = extractHtmlByXPath(selector);
                        } else if ("LIST".equals(extractType)) {
                            extractedValue = extractListByXPath(selector);
                        }
                    } else if ("REGEX".equals(selectorType)) {
                        // 正则表达式
                        extractedValue = extractByRegex(driver.getPageSource(), selector);
                    }
                    
                    // 存储提取的内容
                    if (extractedValue != null) {
                        content.put(rule.getFieldName(), extractedValue);
                    } else if (rule.getRequired()) {
                        log.warn("必填字段 {} 未能提取到内容", rule.getFieldName());
                    }
                    
                } catch (Exception e) {
                    log.error("提取字段 {} 失败: {}", rule.getFieldName(), e.getMessage());
                    if (rule.getRequired()) {
                        return Collections.emptyMap();
                    }
                }
            }
        } catch (Exception e) {
            log.error("提取内容失败", e);
        }
        
        return content;
    }

    /**
     * 加载爬虫规则
     */
    private void loadRules() {
        if (task.getRuleId() != null) {
            // 加载指定的规则
            CrawlerRule rule = ruleRepository.selectById(task.getRuleId());
            if (rule != null) {
                rules = Collections.singletonList(rule);
            }
        } else {
            // 加载所有规则
            rules = ruleRepository.selectList(null);
        }
    }

    /**
     * 加载动态页面参数
     */
    private void loadDynamicParams() {
        // 从任务配置中加载动态参数
        try {
            if (task != null && task.getConfig() != null) {
                dynamicParams = objectMapper.readValue(task.getConfig(), DynamicPageParamsDTO.class);
            }
        } catch (Exception e) {
            log.error("加载动态页面参数失败", e);
        }
    }

    @Override
    public void cleanup() {
        super.cleanup();
        if (driver != null) {
            try {
                driver.quit();
            } catch (Exception e) {
                log.error("关闭WebDriver失败", e);
            }
            driver = null;
        }
    }

    /**
     * 停止爬虫任务
     */
    @Override
    public void stop() {
        log.info("停止动态爬虫任务 {}", task != null ? task.getId() : "未初始化");
        running.set(false);
        if (driver != null) {
            try {
                driver.quit();
            } catch (Exception e) {
                log.error("关闭WebDriver失败", e);
            }
            driver = null;
        }
    }

    /**
     * 暂停爬虫任务
     */
    @Override
    public void pause() {
        log.info("暂停动态爬虫任务 {}", task != null ? task.getId() : "未初始化");
        paused.set(true);
    }

    /**
     * 从暂停状态恢复爬虫任务
     */
    @Override
    public void resume() {
        log.info("恢复动态爬虫任务 {}", task != null ? task.getId() : "未初始化");
        paused.set(false);
    }

    @Override
    public void addUrlFilter(String pattern, boolean include) {
        super.addUrlFilter(pattern, include);
    }

    @Override
    public void addPageProcessor(String processorClass, Map<String, Object> params) {
        super.addPageProcessor(processorClass, params);
    }

    @Override
    public void addPipeline(String pipelineClass, Map<String, Object> params) {
        super.addPipeline(pipelineClass, params);
    }

    @Override
    public void setDepth(int depth) {
        super.setDepth(depth);
    }

    @Override
    public void setThreadCount(int threadCount) {
        super.setThreadCount(threadCount);
    }

    @Override
    public void addSeedUrl(String url) {
        super.addSeedUrl(url);
    }

    @Override
    public void setProxyStrategy(String strategy) {
        super.setProxyStrategy(strategy);
    }

    @Override
    public void enableCaptchaHandler(boolean enabled) {
        super.enableCaptchaHandler(enabled);
    }

    @Override
    public void setFailureHandlingStrategy(String strategy, int maxRetries) {
        super.setFailureHandlingStrategy(strategy, maxRetries);
    }

    /**
     * 执行JavaScript脚本
     * 在页面上下文中执行自定义JavaScript代码
     *
     * @param script JavaScript代码
     * @return 执行结果
     */
    @Override
    public Object executeJavaScript(String script) {
        if (driver == null) {
            log.error("WebDriver未初始化，无法执行JavaScript");
            return null;
        }
        return executeCustomScript(script);
    }
    
    /**
     * 设置动态页面处理配置
     * 实现接口方法，将配置转换为动态页面参数
     * 
     * @param config 配置参数映射表
     */
    @Override
    public void setDynamicPageConfig(Map<String, Object> config) {
        try {
            if (config == null) {
                dynamicParams = null;
                return;
            }
            
            // 将配置项映射到动态参数
            dynamicParams = new DynamicPageParamsDTO();
            
            if (config.containsKey("waitTime")) {
                dynamicParams.setWaitTime((Integer) config.get("waitTime"));
            }
            
            if (config.containsKey("userAgent")) {
                dynamicParams.setUserAgent((String) config.get("userAgent"));
            }
            
            if (config.containsKey("windowWidth")) {
                dynamicParams.setWindowWidth((Integer) config.get("windowWidth"));
            }
            
            if (config.containsKey("windowHeight")) {
                dynamicParams.setWindowHeight((Integer) config.get("windowHeight"));
            }
            
            if (config.containsKey("takeScreenshot")) {
                dynamicParams.setTakeScreenshot((Boolean) config.get("takeScreenshot"));
            }
            
            if (config.containsKey("customScript")) {
                dynamicParams.setCustomScript((String) config.get("customScript"));
            }
            
            log.info("更新动态页面配置成功");
        } catch (Exception e) {
            log.error("更新动态页面配置失败", e);
        }
    }

    /**
     * 判断URL是否匹配规则
     * 
     * @param url URL
     * @param pattern 匹配模式
     * @return 是否匹配
     */
    private boolean isUrlMatchRule(String url, String pattern) {
        if (pattern == null || pattern.isEmpty()) {
            return true; // 空模式匹配所有URL
        }
        
        try {
            return url.matches(pattern);
        } catch (Exception e) {
            log.error("URL匹配规则失败: {}", pattern, e);
            return false;
        }
    }
    
    /**
     * 使用CSS选择器提取文本
     * 
     * @param selector CSS选择器
     * @return 提取的文本
     */
    private String extractTextByCSS(String selector) {
        try {
            WebElement element = driver.findElement(By.cssSelector(selector));
            return element.getText();
        } catch (Exception e) {
            log.error("使用CSS选择器提取文本失败 {}", selector, e);
            return null;
        }
    }
    
    /**
     * 使用CSS选择器提取属性
     * 
     * @param selector CSS选择器
     * @param attribute 属性名称
     * @return 提取的属性值
     */
    private String extractAttributeByCSS(String selector, String attribute) {
        try {
            WebElement element = driver.findElement(By.cssSelector(selector));
            return element.getAttribute(attribute);
        } catch (Exception e) {
            log.error("使用CSS选择器提取属性失败 {} - {}", selector, attribute, e);
            return null;
        }
    }
    
    /**
     * 使用CSS选择器提取HTML
     * 
     * @param selector CSS选择器
     * @return 提取的HTML内容
     */
    private String extractHtmlByCSS(String selector) {
        try {
            WebElement element = driver.findElement(By.cssSelector(selector));
            return element.getAttribute("outerHTML");
        } catch (Exception e) {
            log.error("使用CSS选择器提取HTML失败", e);
            return null;
        }
    }
    
    /**
     * 使用CSS选择器提取列表
     * 
     * @param selector CSS选择器
     * @return 提取的列表
     */
    @SuppressWarnings("unchecked")
    private List<String> extractListByCSS(String selector) {
        try {
            List<WebElement> elements = driver.findElements(By.cssSelector(selector));
            List<String> result = new ArrayList<>();
            for (WebElement element : elements) {
                result.add(element.getText());
            }
            return result;
        } catch (Exception e) {
            log.error("使用CSS选择器提取列表失败 {}", selector, e);
            return Collections.emptyList();
        }
    }
    
    /**
     * 使用XPath提取文本
     * 
     * @param xpath XPath表达式
     * @return 提取的文本
     */
    private String extractTextByXPath(String xpath) {
        try {
            WebElement element = driver.findElement(By.xpath(xpath));
            return element.getText();
        } catch (Exception e) {
            log.error("使用XPath提取文本失败", e);
            return null;
        }
    }
    
    /**
     * 使用XPath提取属性
     * 
     * @param xpath XPath表达式
     * @param attribute 属性名称
     * @return 提取的属性值
     */
    private String extractAttributeByXPath(String xpath, String attribute) {
        try {
            WebElement element = driver.findElement(By.xpath(xpath));
            return element.getAttribute(attribute);
        } catch (Exception e) {
            log.error("使用XPath提取属性失败 {} - {}", xpath, attribute, e);
            return null;
        }
    }
    
    /**
     * 使用XPath提取HTML
     * 
     * @param xpath XPath表达式
     * @return 提取的HTML内容
     */
    private String extractHtmlByXPath(String xpath) {
        try {
            WebElement element = driver.findElement(By.xpath(xpath));
            return element.getAttribute("outerHTML");
        } catch (Exception e) {
            log.error("使用XPath提取HTML失败", e);
            return null;
        }
    }
    
    /**
     * 使用XPath提取列表
     * 
     * @param xpath XPath表达式
     * @return 提取的列表
     */
    @SuppressWarnings("unchecked")
    private List<String> extractListByXPath(String xpath) {
        try {
            List<WebElement> elements = driver.findElements(By.xpath(xpath));
            List<String> result = new ArrayList<>();
            for (WebElement element : elements) {
                result.add(element.getText());
            }
            return result;
        } catch (Exception e) {
            log.error("使用XPath提取列表失败", e);
            return Collections.emptyList();
        }
    }
    
    /**
     * 使用正则表达式提取内容
     * 
     * @param content 要匹配的内容
     * @param regex 正则表达式
     * @return 提取的内容
     */
    private String extractByRegex(String content, String regex) {
        try {
            java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(regex);
            java.util.regex.Matcher matcher = pattern.matcher(content);
            if (matcher.find()) {
                return matcher.group(1);
            }
            return null;
        } catch (Exception e) {
            log.error("使用正则表达式提取内容失败 {}", regex, e);
            return null;
        }
    }
} 
